﻿using MenuService.Entities;
using MenuService.Manager;
using MenuService.Menu;
using MenuService.Menu.Dto;
using MenuService.Permissions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.PermissionManagement;

namespace MenuService
{
    [Authorize]
    public class AbpMenuAppService : MenuServiceAppService, IAbpMenuAppService
    {
        private readonly MenuManager _menuManager;
        private readonly IRepository<AbpMenu> _menuRepository;
        private readonly IRepository<PermissionGrant, Guid> _permissionGrantRepository;

        public AbpMenuAppService(MenuManager menuManager,
            IRepository<AbpMenu, Guid> menuRepository,
            IRepository<PermissionGrant, Guid> permissionGrantRepository)
        {
            this._menuManager = menuManager;
            this._menuRepository = menuRepository;
            this._permissionGrantRepository = permissionGrantRepository;
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [Authorize(MenuServicePermissions.Menu.Create)]
        public async Task<MenuDto> CreateMenuAsync(MenuCreateOrUpdateDto input)
        {
            var menuEntity = await _menuManager.CreateAsync(input.ParentId, input.ParentIds, input.Name, input.Code, input.Type, input.Icon, input.Router, input.Component, input.Permission, input.Application, input.OpenType, input.IsVisible, input.Link, input.Redirect, input.Weight, input.Sort, input.Remark, input.Status);
            return ObjectMapper.Map<AbpMenu, MenuDto>(menuEntity);
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Authorize(MenuServicePermissions.Menu.Delete)]
        public async Task DeleteMenuAsync(Guid id)
        {
            await _menuRepository.DeleteAsync(x => x.Id == id);
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="id"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="UserFriendlyException"></exception>
        [Authorize(MenuServicePermissions.Menu.Update)]
        public async Task<MenuDto> UpdateMeunAsync(Guid id, MenuCreateOrUpdateDto input)
        {
            var entity = await _menuRepository.FirstOrDefaultAsync(x => x.Id == id);
            if (entity == null) throw new UserFriendlyException("current menu does not exists");
            ObjectMapper.Map<MenuCreateOrUpdateDto, AbpMenu>(input, entity);
            var updatedEntity = await _menuRepository.UpdateAsync(entity);
            return ObjectMapper.Map<AbpMenu, MenuDto>(updatedEntity);
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <returns></returns>
        public async Task<List<MenuDto>> GetListAsync()
        {
            var menus = await _menuRepository.ToListAsync();
            return ObjectMapper.Map<List<AbpMenu>, List<MenuDto>>(menus);
        }

        public async Task<List<MenuDto>> GetCurrentUserMenuAsync()
        {
            if (CurrentUser.Id == null)
                throw new UserFriendlyException("user id is null");
            var permissions = await _permissionGrantRepository.GetQueryableAsync();
            var menus = await _menuRepository.GetQueryableAsync();
            var query = from permission in permissions
                        join menu in menus on permission.Name equals menu.Permission into temp
                        from t in temp.DefaultIfEmpty()
                        where permission.ProviderName == "U" && permission.ProviderKey == CurrentUser.Id.Value.ToString() || permission.ProviderName == "R" && CurrentUser.Roles.Contains(permission.ProviderKey)
                        select t;
            var entities = await query.ToListAsync();
            return ObjectMapper.Map<List<AbpMenu>, List<MenuDto>>(entities);
        }
    }
}
